#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <regex.h>          // 正则表达式
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#define BUFFER_SIZE 128

// 存储从配置文件中读取的串口配置信息
struct Uart
{
    char *Name;
    char *Speed;
    char *Bit;
    char *Event;
    char *Stop;
};
/*------------------------------- 二级函数----------------------------*/
/*-------- 字符串匹配-----*/
// 参数：需要匹配的字符串，匹配规则
char *reStr(char *test_str, char *reg_str)
{
    int i;
    char ebuff[256];
    int cflags;
    regex_t reg;
    regmatch_t rm[5];
    int ret;
    char *part_str = NULL;
    char result[256];

    cflags = REG_EXTENDED | REG_ICASE;

    ret = regcomp(&reg, reg_str, cflags);
    if (ret)
    {
        regerror(ret, &reg, ebuff, 256);
        fprintf(stderr, "%s\n", ebuff);
        exit(-1);
    }
    ret = regexec(&reg, test_str, 10, rm, 0);
    if (ret)
    {   
        regerror(ret, &reg, ebuff, 256);
        fprintf(stderr, "%s\n", ebuff);
        exit(-1);
    }
    for (i = 0; i < 5; i++)
    {
        if (rm[i].rm_so > -1)
        {
            part_str = strndup(test_str+rm[i].rm_so, rm[i].rm_eo-rm[i].rm_so);
            if (i == 1)
                return part_str;
            free(part_str);
            part_str = NULL;
        }
    }
    exit(-1);
}

/*------------------------------- 一级函数----------------------------*/
/*--------串口配置-------*/
// 参数：文件描述符、波特率、数据位、奇偶校验位、停止位
int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio, oldtio;
    //保存测试现有串口参数设置，在这里如果串口号等出错，会有相关的出错信息
    if (tcgetattr(fd, &oldtio) != 0){
        perror("SetipSerial 1");
        return -1;
    }
    bzero(&newtio, sizeof(newtio));
    // 设置字符串大小
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
    // 设置停止位
    switch(nBits)
    {
        case 7:
            newtio.c_cflag |= CS7;
            break;
        case 8:
            newtio.c_cflag |= CS8;
            break;
    }
    switch(nEvent)
    {
        // 奇数
        case 'O':
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_cflag |= (INPCK | ISTRIP);
            break;
        // 偶数
        case 'E':
            newtio.c_cflag |= (INPCK | ISTRIP);
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            break;
        // 无奇偶校验位
        case 'N':
            newtio.c_cflag &= ~PARENB;
            break;
    }
    // 设置波特率
    switch (nSpeed)
    {
        case 2400:
            cfsetispeed(&newtio, B2400);
            cfsetospeed(&newtio, B2400);
            break;
        case 4800:
            cfsetispeed(&newtio, B4800);
            cfsetospeed(&newtio, B4800);
            break;
        case 9600:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
        case 115200:
            cfsetispeed(&newtio, B115200);
            cfsetospeed(&newtio, B115200);
            break;
        case 460800:
            cfsetispeed(&newtio, B460800);
            cfsetospeed(&newtio, B460800);
            break;
        default:
            cfsetispeed(&newtio, B9600);
            cfsetospeed(&newtio, B9600);
            break;
    }
    // 设置停止位
    if(nStop == 1)
        newtio.c_cflag &= ~CSTOPB;
    else if ( nStop == 2 )
        newtio.c_cflag |= CSTOPB;
    // 设置等待时间和最小接收字符
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;
    // 处理未接收字符
    tcflush(fd, TCIFLUSH);
    // 激活新配置
    if (( tcsetattr(fd, TCSANOW, &newtio)) != 0)
    {
        perror("com set error");
        return -1;
    }
    printf("set done!\n");
    return 0;
}

/*-------- 打开串口-----*/
// 参数：端口号
int open_port(int comport)
{
    int fd;
    char *dev[] = {"/dev/ttyAMA0","/dev/ttyAMA1","/dev/ttyAMA2"};
    long vdisable;
    if (comport == 1)       // 串口1
    {
        fd = open("/dev/ttyAMA0",O_RDWR|O_NOCTTY|O_NDELAY);
        if ( -1 == fd){
            perror("Can,t Open Serial Port");
            return -1;
        }
    }
    if (comport == 2)       // 串口2
    {
        fd = open("/dev/ttyAMA1",O_RDWR|O_NOCTTY|O_NDELAY);
        if ( -1 == fd){
            perror("Can,t Open Serial Port");
            return -1;
        }
    }
    if (comport == 3)       // 串口3
    {
        fd = open("/dev/ttyAMA2",O_RDWR|O_NOCTTY|O_NDELAY);
        if ( -1 == fd){
            perror("Can,t Open Serial Port");
            return -1;
        }
    }
    // 恢复串口为阻塞状态
    if(fcntl(fd, F_SETFL, 0) < 0 )
        printf("fcntl failed!\n");
    else
        printf("fcntl = %d\n",fcntl(fd, F_SETFL, 0));
    //测试是否为终端设备
    if(isatty(STDIN_FILENO) == 0)
        printf("standard input is not a terminal device \n");
    else
        printf("isatty success!\n");
    printf("fd-open=%d\n",fd);
    return fd;
}

/*-------- 读取配置文件-----*/
// 参数：文件路径、Uart结构体指针。结果从指针中取出
// 缺陷：只能读取设定好的键
int readConfig(char *filePath, struct Uart *mmp)
{
    char buf[1024];
    FILE *fp;

    if ((fp = fopen(filePath, "r")) == NULL)
    {
        perror("fail to fopen");
        return -1;
    }

    char *myresult = NULL;
    char *myKey = NULL; 
    char *reg_str = "= (.*)";
    char *first_str = "(.*) =";
    while (fgets(buf, 1024, fp) != NULL)
    {
        if (strchr(buf,'=') == NULL)
        {
            continue;
        }
        myKey = reStr(buf, first_str);
        myresult = reStr(buf, reg_str);
        // strncmp 完全相等返回0
        if (strncmp(myKey,"Name",4) == 0)
            mmp->Name = myresult;
        if (strncmp(myKey,"Speed",5) == 0)
            mmp->Speed = myresult;
        if (strncmp(myKey,"Bit",3) == 0)
            mmp->Bit = myresult;
        if (strncmp(myKey,"Event",5) == 0)
            mmp->Event = myresult;
        if (strncmp(myKey,"Stop",3) == 0)
            mmp->Stop = myresult;
    }
    fclose(fp);
    return 0;
}

/*-------- TCP通信服务端-----*/
int tcp_server(char sendBuf[], char ipAddress[], char Port[])
{
    int listenfd, connfd;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t peerlen;
	char buf[BUFFER_SIZE];

	/*建立socket连接*/
	if ((listenfd = socket(AF_INET,SOCK_STREAM,0))== -1)
	{
		perror("socket");
		exit(1);
	}
	printf("listenfd = %d\n",listenfd);
	
	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;              // IPV4协议
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);
	
	
	/*绑定函数bind()*/
	if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
	{
		perror("bind");
		exit(1);
	}
	printf("Bind success!\n");
	
	/*调用listen()函数，创建未处理请求的队列*/
	if (listen(listenfd, 10) == -1)
	{
		perror("listen");
		exit(1);
	}
	printf("Listening....\n");
	
	/*调用accept()函数，等待客户端的连接*/
    peerlen = sizeof(cliaddr);
    while(1)
    {
        if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &peerlen)) < 0)
        {
            perror("accept");
            exit(1);
        }
        
        /*调用recv()函数接收客户端的请求*/
        memset(buf , 0, sizeof(buf));
        if ((recv(connfd, buf, BUFFER_SIZE, 0)) == -1)
        {
            perror("recv");
            exit(1);
        }
        printf("Received a message: %s\n", buf);
        send(connfd, sendBuf, BUFFER_SIZE, 0);
        close(connfd);
    }
	close(listenfd);
}
/*-------- TCP通信客户端-----*/
int tcp_client(char sendBuf[], char ipAddress[], char Port[])
{
    int sockfd;
	char buf[BUFFER_SIZE] = "Hello Service";
	struct sockaddr_in servaddr;

	/*创建socket*/
	if ((sockfd= socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket");
		exit(1);
	}

	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);

	/*调用connect函数主动发起对服务器端的连接*/
	if(connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr))== -1)
	{
		perror("connect");
		exit(1);
	}
	/*发送消息给服务器端*/
	if ((send(sockfd, sendBuf, strlen(sendBuf), 0)) == -1)
	{
		perror("send");
		exit(1);
	}
    if (recv(sockfd, buf, sizeof(buf), 0) == -1)
    {
        perror("recv");
        exit(-1);
    }
    printf("recv from server:%s\n",buf);
	close(sockfd);
}
/*-------- UDP通信服务端-----*/
int udp_server(char sendBuf[], char ipAddress[], char Port[])
{
    int sockfd;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t peerlen;
	char buf[BUFFER_SIZE];

	/*建立socket连接*/
	if ((sockfd = socket(AF_INET,SOCK_DGRAM,0))== -1)
	{
		perror("socket");
		exit(1);
	}
	printf("sockfd = %d\n",sockfd);
	
	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);
	
	
	/*绑定函数bind()*/
	if (bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
	{
		perror("bind");
		exit(1);
	}
	printf("Bind success!\n");
	
	// 调用recvfrom（）函数，等待接收客户端的数据
    peerlen = sizeof(cliaddr);
    while(1)
    {
        if (( recvfrom(sockfd, buf,sizeof(buf), 0, (struct sockaddr *)&cliaddr, &peerlen)) < 0)
        {
            perror("recvfrom");
            exit(1);
        }
        printf("Received a message: %s\n", buf);
        sendto(sockfd, sendBuf, sizeof(buf), 0, (struct sockaddr *)&cliaddr, peerlen);
    }
	close(sockfd);
    return 0;
}

/*-------- UDP通信客户端-----*/
int udp_client(char sendBuf[], char ipAddress[], char Port[])
{
    int sockfd;
	char buf[BUFFER_SIZE] = "Hello Service";
	struct sockaddr_in servaddr; 

	/*创建socket*/
	if ((sockfd= socket(AF_INET, SOCK_DGRAM, 0)) == -1)
	{
		perror("socket");
		exit(1);
	}
	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);
	/*发送消息给服务器端*/
	if (sendto(sockfd, sendBuf, strlen(sendBuf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
	{
		perror("send");
		exit(1);
	}
    if (recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL) < 0)
    {
        perror("recvfrom");
        exit(-1);
    }
    printf("recv from server:%s\n",buf);
	close(sockfd);
	return 0;
}
/* --------------------------- TCP循环型服务器---------------------- */
// TCP服务器端(循环型)，把接受到客户端的数据发送给客户端
int tcpServer_return(char ipAddress[], char Port[])
{
    int listenfd, connfd, n;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t peerlen;
	char buf[BUFFER_SIZE];

	/*建立socket连接*/
	if ((listenfd = socket(AF_INET,SOCK_STREAM,0))== -1)
	{
		perror("socket");
		exit(1);
	}
	printf("listenfd = %d\n",listenfd);
	
	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);
	
	
	/*绑定函数bind()*/
	if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
	{
		perror("bind");
		exit(1);
	}

	
	/*调用listen()函数，创建未处理请求的队列*/
	if (listen(listenfd, 10) == -1)
	{
		perror("listen");
		exit(1);
	}

	/*调用accept()函数，等待客户端的连接*/
    peerlen = sizeof(cliaddr);
    while(1)
    {
        if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &peerlen)) < 0)
        {
            perror("accept");
            exit(1);
        }
        printf("connection from [%s:%d]\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
        /*调用recv()函数接收客户端的请求*/
        
        while ((n = recv(connfd, buf, BUFFER_SIZE, 0)) > 0)
        {
            printf("echo : %s", buf);
            send(connfd, buf, n, 0);
            // 注释掉的下面代码，使服务器端可以一直保持服务状态。
            // exit(1);
        }
        printf("client is closed\n");
        close(connfd);
    }
	close(listenfd);
    return 0;
}
// 这个加入需要向客户端返回的参数，用于发送串口读写的数据

int tcpServer_return_send(char ipAddress[], char Port[], char sendData[])
{
    int listenfd, connfd, n;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t peerlen;
	char buf[BUFFER_SIZE];

	/*建立socket连接*/
	if ((listenfd = socket(AF_INET,SOCK_STREAM,0))== -1)
	{
		perror("socket");
		exit(1);
	}
	printf("listenfd = %d\n",listenfd);
	
	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);
	
	
	/*绑定函数bind()*/
	if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
	{
		perror("bind");
		exit(1);
	}

	
	/*调用listen()函数，创建未处理请求的队列*/
	if (listen(listenfd, 10) == -1)
	{
		perror("listen");
		exit(1);
	}

	/*调用accept()函数，等待客户端的连接*/
    peerlen = sizeof(cliaddr);
    while(1)
    {
        if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &peerlen)) < 0)
        {
            perror("accept");
            exit(1);
        }
        printf("connection from [%s:%d]\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
        /*调用recv()函数接收客户端的请求*/
        
        while ((n = recv(connfd, buf, BUFFER_SIZE, 0)) > 0)
        {
            printf("echo : %s", buf);
            send(connfd, sendData, strlen(sendData), 0);
            // 注释掉的下面代码，使服务器端可以一直保持服务状态。
            exit(1);
        }
        printf("client is closed\n");
        close(connfd);
    }
	close(listenfd);
    return 0;
}


// TCP客户端(循环型)，从键盘读取输入的数据发送给服务端。
// 因为是循环型，如果这个客户端一直在输入状态，下一个服务器就不能连接了(发送的数据一直处于等待状态，服务器没有响应)
int tcpClient_input(char ipAddress[], char Port[])
{
    int sockfd;
	char buf[BUFFER_SIZE];
	struct sockaddr_in servaddr;
	

	/*创建socket*/
	if ((sockfd= socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket");
		exit(1);
	}

	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);

	/*调用connect函数主动发起对服务器端的连接*/
	if(connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr))== -1)
	{
		perror("connect");
		exit(1);
	}
    // 循环从键盘输入
    while (1)
    {
        printf("input > ");
        fgets(buf, sizeof(buf), stdin);
        if (strcmp(buf, "quit \n") == 0)
            break;
        // 发送消息给服务器端
        send(sockfd, buf, sizeof(buf), 0);
        bzero(buf, sizeof(buf));
        // 接收服务器端发回的消息
        recv(sockfd, buf, sizeof(buf), 0);
        printf("recv from server :%s\n", buf);
    }
    printf("client exit\n");
    close(sockfd);
    return 0;
}

// 增加参数，将串口读取的数据作为参数，传给服务器端
int tcpClient_input_send(char ipAddress[], char Port[], char sendData[])
{
    int sockfd;
	char buf[BUFFER_SIZE];
	struct sockaddr_in servaddr;
	

	/*创建socket*/
	if ((sockfd= socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		perror("socket");
		exit(1);
	}

	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);

	/*调用connect函数主动发起对服务器端的连接*/
	if(connect(sockfd,(struct sockaddr *)&servaddr, sizeof(servaddr))== -1)
	{
		perror("connect");
		exit(1);
	}

        // 发送消息给服务器端
        send(sockfd, sendData, strlen(sendData), 0);
        bzero(buf, sizeof(buf));
        // 接收服务器端发回的消息
        recv(sockfd, buf, sizeof(buf), 0);
        printf("recv from server :%s\n", buf);
    printf("client exit\n");
    close(sockfd);
    return 0;
}
/* --------------------------- TCP并发型服务器---------------------- */
// 服务器端
int tcpServer_echo(char ipAddress[], char Port[])
{
    int listenfd, connfd, n;
    pid_t pid;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t peerlen;
	char buf[BUFFER_SIZE];

	/*建立socket连接*/
	if ((listenfd = socket(AF_INET,SOCK_STREAM,0))== -1)
	{
		perror("socket");
		exit(1);
	}
	
	/*设置sockaddr_in 结构体中相关参数*/
    bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(atoi(Port));
	servaddr.sin_addr.s_addr = inet_addr(ipAddress);
	
	/*绑定函数bind()*/
	if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
	{
		perror("bind");
		exit(1);
	}

	/*调用listen()函数，创建未处理请求的队列*/
	if (listen(listenfd, 10) == -1)
	{
		perror("listen");
		exit(1);
	}
    // 忽略SIGCHLD信号，避免僵死进程
    signal(SIGCHLD, SIG_IGN);
	
	/*调用accept()函数，等待客户端的连接*/
    peerlen = sizeof(cliaddr);
    while(1)
    {
        if ((connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &peerlen)) < 0)
        {
            perror("accept");
            exit(1);
        }
        printf("connection from [%s:%d]\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
        
        
        // 创建子进程
        if((pid = fork()) < 0)
        {
            perror("fork");
            exit(-1);
        }
        else if (pid == 0)
        {
            /*调用recv()函数接收客户端的请求*/
            while ((n = recv(connfd, buf, BUFFER_SIZE, 0)) > 0)
            {
                printf("echo : %s", buf);
                send(connfd, buf, n, 0);
                // exit(1);
            }
                printf("client is closed\n");
                // 子进程结束
                exit(0);
            }
            else
            {
                close(connfd);
            }
    }
	close(listenfd);
    return 0;
}

/*          main函数示例代码
-------------------------读取配置文件-------------------------
    struct Uart mmUart = {}; 
    struct Uart *mp;
    mp = &mmUart;
    readConfig("config.ini", mp);
    // printf("main:%s",mp->Name);
    printf("end %s",mp->Name);
    printf("end %s",mp->Speed);
    printf("end %s",mp->Bit);
    printf("end %s",mp->Event);
    printf("end %s",mp->Stop);
-------------------------打开串口、配置串口-------------------------
    int fd;
    char buff[BUFFER_SIZE];

    // 打开串口
    if((fd = open_port(1)) < 0)
    {
        perror("open_port error");
        return -1;
    }

    // 配置串口
    if((set_opt(fd, 115200, 8, 'N', '1')) < 0){ 
        perror("set_opt error");
        return -1;
    }   
    // 向串口发送数据
	do
	{
		printf("Input some words(enter 'quit' to exit):");
		memset(buff, 0, BUFFER_SIZE);
		if (fgets(buff, BUFFER_SIZE, stdin) == NULL)
		{
			perror("fgets");
			break;
		}
		write(fd, buff, strlen(buff));
	} while(strncmp(buff, "quit", 4));
    close(fd);
---------------------TCP通信服务端---------------------
    char buf[BUFFER_SIZE] = "hello,liangxinxin";
    char ipAddress[] = "0.0.0.0";
    char Port[] = "9999";
    tcp_server(buf, ipAddress, Port);
---------------------TCP通信客户端---------------------
    char buf[BUFFER_SIZE] = "hello,liangxinxin client send";
    char ipAddress[] = "0.0.0.0";
    char Port[] = "9999";
    tcp_client(buf, ipAddress, Port);
---------------------UDP通信---------------------
    char buf[BUFFER_SIZE] = "hello,liangxinxin server send";
    char ipAddress[] = "0.0.0.0";
    char Port[] = "9999";
    udp_server(buf, ipAddress, Port);
    // udp_client(buf, ipAddress, Port);

---------------------TCP循环型服务器---------------------
    char ipAddress[] = "0.0.0.0";
    char Port[] = "9999";
    tcpServer_return(ipAddress,Port);
    // tcpClient_input(ipAddress,Port);
---------------------TCP并发型服务器---------------------
    char ipAddress[] = "0.0.0.0";
    char Port[] = "9999";
    tcpServer_echo(ipAddress,Port);
*/